using System;
using System.Drawing;
using Sherwood.Imaging.Providers;

namespace Sherwood.Imaging.Behaviors
{
    public class SizeAndClipBehavior : ResizeBehavior
    {
        /// <exception cref="NotSupportedException">at least one of the parameters keepWidth or keepHeight must be true</exception>
        public SizeAndClipBehavior(bool keepWidth, bool keepHeight)
            : this(new StaticBooleanProvider(keepWidth), new StaticBooleanProvider(keepHeight))
        {
        }

        /// <exception cref="NotSupportedException">at least one of the parameters keepWidth or keepHeight must be true</exception>
        public SizeAndClipBehavior(bool keepWidth, IBooleanProvider keepHeight)
            : this(new StaticBooleanProvider(keepWidth), keepHeight)
        {
        }

        /// <exception cref="NotSupportedException">at least one of the parameters keepWidth or keepHeight must be true</exception>
        public SizeAndClipBehavior(IBooleanProvider keepWidth, bool keepHeight)
            : this(keepWidth, new StaticBooleanProvider(keepHeight))
        {
        }

        /// <exception cref="NotSupportedException">at least one of the parameters keepWidth or keepHeight must be true</exception>
        public SizeAndClipBehavior(IBooleanProvider keepWidth, IBooleanProvider keepHeight)
        {
            KeepHeight = keepHeight;
            KeepWidth = keepWidth;
        }

        public IBooleanProvider KeepHeight { get; set; }
        public IBooleanProvider KeepWidth { get; set; }

        public override void DoResize(Size original, int? maxWidth, int? maxHeight, out Size newSize, out Rectangle sourceRectangle)
        {
            sourceRectangle = new Rectangle(Point.Empty, original);

            double width = original.Width;
            double height = original.Height;
            double ratio = width/height;

            bool setByHeight;
            var keepHeight = KeepHeight.GetValue();
            var keepWidth = KeepWidth.GetValue();
            if (keepHeight && keepWidth && maxHeight.HasValue && maxWidth.HasValue)
            {
                var tmpWidth = width;
                var tmpHeight = height;
                if (tmpWidth > maxWidth.Value)
                {
                    tmpWidth = maxWidth.Value;
                    tmpHeight = tmpWidth / ratio;
                }
                setByHeight = tmpHeight < maxHeight;
            }
            else
                setByHeight = keepHeight;
            if (setByHeight)
            {
                if (maxHeight.HasValue && height > maxHeight.Value)
                {
                    height = maxHeight.Value;
                    width = height*ratio;
                }
                if (maxWidth.HasValue && width > maxWidth.Value)
                {
                    width = maxWidth.Value;

                    double newRatio = width/height;
                    int orgWidth = Convert.ToInt32(original.Height*newRatio);
                    sourceRectangle = new Rectangle(Convert.ToInt32((sourceRectangle.Width - orgWidth)/2), 0,
                                                    orgWidth, sourceRectangle.Height);
                }
            }
            else
            {
                if (maxWidth.HasValue && width > maxWidth.Value)
                {
                    width = maxWidth.Value;
                    height = width/ratio;
                }
                if (maxHeight.HasValue && height > maxHeight.Value)
                {
                    height = maxHeight.Value;

                    double newRatio = width/height;
                    int orgHeight = Convert.ToInt32(original.Width/newRatio);
                    sourceRectangle = new Rectangle(0, Convert.ToInt32((sourceRectangle.Height - orgHeight)/2),
                                                    sourceRectangle.Width, orgHeight);
                }
            }
            newSize = new Size((int) width, (int) height);
        }
    }
}